;==========================================
; David Young CS:A Final Project Bootloader
;==========================================
[ORG 0x7C00]
jmp main
;==========================================
;OEM Parameter block (bpb prefix = BIOS Parameter Block)
;==========================================
 
bpbOEM			db "DavidOS "
bpbBytesPerSector:  	dw 512
bpbSectorsPerCluster: 	db 1
bpbReservedSectors: 	dw 1
bpbNumberOfFATs: 		db 2
bpbRootEntries: 		dw 224
bpbTotalSectors: 		dw 2880
bpbMedia: 	        	db 0xF0
bpbSectorsPerFAT: 		dw 9
bpbSectorsPerTrack: 	dw 18
bpbHeadsPerCylinder: 	dw 2
bpbHiddenSectors:       dd 0
bpbTotalSectorsBig:     dd 0
bsDriveNumber: 	        db 0
bsUnused: 	        	db 0
bsExtBootSignature: 	db 0x29
bsSerialNumber:	        dd 0xa0a1a2a3
bsVolumeLabel: 	        db "MOS FLOPPY "
bsFileSystem: 	        db "FAT12   "
 
;==========================================
;Routines
;==========================================
;--------------------
;Print character function
;AL - Character to write
;--------------------
printChar:
	mov ah, 0Eh
	xor bx, bx
	ret

;--------------------
;Print string function
;SP - The address of the null terminated string
;to output
;--------------------
printStr:
	lodsb
	or			al, al				; al=current character
	jz			PrintDone			; null terminator found
	mov			ah,	0eh			; get next character
	int			10h
	jmp			printStr
PrintDone:
	ret


;--------------------
;Extended read function
;Disk address packet must be complete
;--------------------
extRead:
	mov ah, 42h
	mov dl, 80h
	mov si, dapacket
	ret

;--------------------
;Cluster to LBA
;--------------------
ClusterLBA:
	sub     ax, 0x0002                          ; zero base cluster number
	xor     cx, cx
	mov     cl, BYTE [bpbSectorsPerCluster]     ; convert byte to word
	mul     cx
	add     ax, WORD [datasector]               ; base data sector
	ret
	
;--------------------
;Something b0rked. Restart.
;--------------------
FAILURE:
	mov si, failmsg
	call printStr
	cli
	hlt

	
	
;==========================================	
;ENTRY POINT
;==========================================
main:
	cli
	xor ax, ax
	mov ds, ax
	mov ss, ax
	mov sp, 0xFFFF	;Stack pointer - 200h past start of code
	sti
	
	mov si, startmsg
	call printStr

;Compute size of root directory
getrootsize:
	mov ax, 0020h
	mul	WORD [bpbRootEntries]
	div WORD [bpbBytesPerSector]
	mov WORD [numblocks], ax

;Get the starting sector of the root directory
getrootstart:
	mov     al, BYTE [bpbNumberOfFATs]            ; number of FATs
	mul     WORD [bpbSectorsPerFAT]               ; sectors used by FATs
	add     ax, WORD [bpbReservedSectors]         ; adjust for bootsector
	mov     WORD [datasector], ax                 ; base of root directory
	add     WORD [datasector], cx
	mov		WORD[startsec], ax

;Load root directory to 7c00h:0200h
loadroot:
	mov WORD [transbuffs], 7c00h
	mov WORD [transbuffo], 0200h
	call extRead

;Browse root directory for kernel image
findimage:
	mov     cx, [bpbRootEntries]
	mov     di, 0x0200       
	.LOOP:
		push    cx
		mov     cx, 11           
		mov     si, kentryfile 
		push    di
		rep  cmpsb                  
		pop     di
		je      loadfat        
		pop     cx
		add     di, 32           
		loop    .LOOP
		jmp     FAILURE           

;Load FAT
loadfat:
	;Starting cluster
	mov dx, [di + 001Ah] ;Store starting cluster num from byte 26
	mov WORD [cluster], dx
	
	;Number of sectors per FAT
	xor ax, ax
	mov al, BYTE [bpbNumberOfFATs]
	mul WORD [bpbSectorsPerFAT]
	mov WORD [numblocks], ax
	
	;FAT starting sector
	mov ax, WORD [bpbReservedSectors]
	mov WORD [startsec], ax

	call extRead
	
	mov al, '.'
    call printChar
	
	
	mov ax, 0x0050
	mov WORD[transbuffs], ax
	mov es, ax                              ; destination for image
	mov bx, 0x0000                          ; destination for image
	push bx
	
;Get the first cluster in the FAT
loadclusterfromfat:
	;Set transfer buffer to 0050h:[BX]
	pop bx
	mov WORD[transbuffo], bx
	
	;Compute starting sector (LBA)
	mov ax, [cluster]
	call ClusterLBA
	mov WORD [startsec], ax
	
	;Computer number of sectors to transfer
	xor cx, cx
	mov cl, BYTE [bpbSectorsPerCluster]
	mov BYTE [numblocks], cl
	
	call extRead
	
	; compute next cluster

	mov     ax, WORD [cluster]                  ; identify current cluster
	mov     cx, ax                              ; copy current cluster
	mov     dx, ax                              ; copy current cluster
	shr     dx, 0x0001                          ; divide by two
	add     cx, dx                              ; sum for (3/2)
	mov     bx, 0x0200                          ; location of FAT in memory
	add     bx, cx                              ; index into FAT
	mov     dx, WORD [bx]                       ; read two bytes from FAT
	test    ax, 0x0001
	jnz     .ODD_CLUSTER

	.EVEN_CLUSTER:
		and     dx, 0000111111111111b               ; take low twelve bits
		jmp     .DONE

	.ODD_CLUSTER:
		shr     dx, 0x0004                          ; take high twelve bits

	.DONE:
		mov     WORD [cluster], dx                  ; store new cluster
		cmp     dx, 0x0FF0                          ; test for end of file
		jb      LOAD_IMAGE

	DONE:
		mov     si, msgCRLF
		call    Print
		push    WORD 0x0050
		push    WORD 0x0000
		retf
		
	;DELETEME <-----------------------------------------------------------------------------------------
	cli
	hlt
	
;==========================================
;DATA
;==========================================
startmsg	db	"Booting...",0
failmsg		db  "F-REST",0
kentryfile	db  "KERNEL  SYS"
datasector  dw 0x0000

cluster		dw  0000h
;--------------------
;Disk Address Packet
;--------------------
dapacket	db	10h		;Size of packet
			db	00h		;Reserved
numblocks	dw	1		;Number of blocks to transfer
transbuffo	dw 	0		;Transfer buffer offset
transbuffs	dw	0		;Transfer buffer segment

startsec	dq	0		;Starting absolute block number
	
;==========================================
times 510-($-$$) db 0  ;Enforce 512 byte file size.
dw 0xAA55        	  ;Boot signature
;==========================================